package amqplib

import (
	"sync"
	"time"

	"github.com/streadway/amqp"
)

type RabbitMQ struct {
	pool       *ConnectionPool
	config     *MQConnectorConfig
	channelMap map[string]*amqp.Channel // 通道缓存
	mu         sync.RWMutex
}

type RabbitMQFactory struct {
	rsm map[string]*RabbitMQ
}

// MQConnectorConfig connector config
type MQConnectorConfig struct {
	Host         string `yaml:"host" json:"host"`
	Port         int    `yaml:"port" json:"port"`
	Path         string `yaml:"virtualHost" json:"virtualHost"`
	User         string `yaml:"username" json:"username"`
	Password     string `yaml:"password" json:"password"`
	Timeout      int    `yaml:"timeout" json:"timeout"`
	Heartbeat    int    `yaml:"heartbeat" json:"heartbeat"`
	SSHTunnelDSN string `yaml:"sshTunnel" json:"sshTunnel"`
}

type MQConnectorConfigMap struct {
	mccm map[string]MQConnectorConfig
	cpc  ConnectionPoolConfig
}

// MQConsumerMessage consumer message
type MQConsumerMessage struct {
	Queue         string    `json:"queue"`
	CorrelationID string    `json:"correlationId"`
	ReplyTo       string    `json:"replyTo"`
	MessageID     string    `json:"messageId"`
	Exchange      string    `json:"exchange"`
	RoutingKey    string    `json:"routingKey"`
	ExchangeType  string    `json:"exchangeType"`
	Durable       bool      `json:"durable"`
	Timestamp     time.Time `json:"-"`
	Body          []byte    `json:"body"`
	AutoAck       bool
	ConsumerTag   string
	Callback      MQConsumerCallback
}

// MQPublishMessage publish message
type MQPublishMessage struct {
	Body          []byte                 `json:"body"`
	Exchange      string                 `json:"exchange"`
	RoutingKey    string                 `json:"routingKey"`
	ExchangeType  string                 `json:"exchangeType"`
	Durable       bool                   `json:"durable"`
	CorrelationID string                 `json:"correlationId"`
	ReplyTo       string                 `json:"replyTo"`
	MessageID     string                 `json:"messageId"`
	Response      chan MQConsumerMessage `json:"-"`
	Timestamp     time.Time              `json:"-"`
	SkipExchange  bool                   // if publish a message only to a queue, not bind to exchange
}

type MQConsumerCallback func(amqp.Delivery) *MQPublishMessage

// ConnectionPool 连接池结构
type ConnectionPool struct {
	config       MQConnectorConfig     // 连接配置
	pool         chan *amqp.Connection // 连接池
	maxIdle      int                   // 最大空闲连接数
	maxActive    int                   // 最大活动连接数
	activeCount  int                   // 当前活动连接数
	idleTimeout  time.Duration         // 空闲超时时间
	lock         sync.Mutex            // 锁
	isClosed     bool                  // 连接池是否已关闭
	waitConnTime time.Duration         // 获取连接等待时间
}

type ConnectionPoolConfig struct {
	maxIdle      int           // 最大空闲连接数
	maxActive    int           // 最大活动连接数
	idleTimeout  time.Duration // 空闲超时时间
	waitConnTime time.Duration // 等待空闲连接时间
}
